#ifndef _NE_ATLAS_H
#define _NE_ATLAS_H

#include <graphics/Texture.h>
#include <graphics/Sprite.h>
#include <graphics/DynamicGeometry.h>
#include <system/Resource.h>

namespace ne
{
    class NEAPI Atlas : public Resource
    {
        public:
            Atlas(ResourceManager *pManager,
                  const uint64_t id,
                  const std::string &name,
                  const std::string &fileName,
                  const bool isManual,
                  ManualResourceLoader *pLoader);

            void setTexture(const TexturePtr &pTexture);
            const TexturePtr& getTexture() const;

            uint32_t getWidth() const;
            uint32_t getHeight() const;

            bool genSpriteGeometry(const std::string &name, const DynamicGeometryPtr &pGeometry,
                                   const Vector3 &pos, const Vector3 &xAxis, const Vector3 &yAxis,
                                   const Vector2 &size, const Color &color=Color::WHITE);

            bool genCommonSpriteGeometry(const Sprite *pSprite, const DynamicGeometryPtr &pGeometry,
                                         const Vector3 &pos, const Vector3 &xAxis, const Vector3 &yAxis,
                                         const Vector2 &size, const Color &color=Color::WHITE);

            bool genSlicedSpriteGeometry(const Sprite *pSprite, const DynamicGeometryPtr &pGeometry,
                                         const Vector3 &pos, const Vector3 &xAxis, const Vector3 &yAxis,
                                         const Vector2 &size, const Color &color=Color::WHITE);

            bool hasSprite(const std::string &name) const;

            Sprite* getSprite(const std::string &name) const;

            Sprite* createSprite(const std::string &name);

            bool destroySprite(const std::string &name);

            void destroyAllSprites();

            virtual ~Atlas();

        protected:
            virtual bool loadImplement();

            virtual bool unloadImplement();

            virtual bool downloadImplement();

            virtual size_t _calculateSize() const;

        private:
            TexturePtr mpTexture;
            SpriteMap mSpriteMap;
    };

    class NEAPI AtlasPtr : public SharedPtr<Atlas>
    {
        public:
            AtlasPtr() : SharedPtr<Atlas>() {}
            explicit AtlasPtr(Atlas *pAtlas) : SharedPtr<Atlas>(pAtlas) {}
            AtlasPtr(const AtlasPtr &pAtlas) : SharedPtr<Atlas>(pAtlas) {}

            AtlasPtr(const ResourcePtr &p)
                : SharedPtr<Atlas>()
            {
                mpPtr = static_cast<Atlas*>(p.ptr());
                mpUseCount = p.getUseCountPtr();
                if (mpUseCount)
                {
                    ++(*mpUseCount);
                }
            }

            AtlasPtr& operator = (const ResourcePtr &p)
            {
                if (mpPtr == static_cast<Atlas*>(p.ptr()))
                {
                    return *this;
                }
                AtlasPtr temp(p);
                swap(temp);
                return *this;
            }
    };
}

#endif
